package com.fxz.bean.factory.support;

import cn.hutool.core.collection.CollectionUtil;
import com.fxz.bean.definition.BeanDefinition;
import com.fxz.bean.definition.PropertyValue;
import com.fxz.bean.definition.RuntimeBeanReference;
import com.fxz.bean.definition.TypeStringValue;
import com.fxz.bean.factory.AutowireCapableBeanFactory;
import com.fxz.bean.utils.ReflectionUtils;

import java.util.List;

/**
 * 自动装配工厂 抽象类
 * 做了根据BeanDefinition创建bean的具体实现
 *
 * @author Fxz
 * @version 1.0
 * @date 2021-08-12 15:37
 */
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {


    /**
     * 通过BeanDefinition创建bean
     *
     * @param beanDefinition
     * @return
     */
    @Override
    public Object createBean(BeanDefinition beanDefinition) {
        //获取bean的全限定类名
        String className = beanDefinition.getClassName();
        //将className转化为Class类型
        Class<?> cls = resolveClassName(className);
        if (cls == null) {
            return null;
        }
        //将Class实例化object
        Object singleton = createBeanInstance(cls);

        //填充属性
        populateBean(singleton, beanDefinition);

        //初始化
        //.......
        return singleton;
    }

    /**
     * 填充bean的属性
     *
     * @param singleton
     * @param beanDefinition
     */
    private void populateBean(Object singleton, BeanDefinition beanDefinition) {
        //通过BeanDefinition获取到propertyValues
        List<PropertyValue> propertyValues = beanDefinition.getPropertyValues();
        if (CollectionUtil.isEmpty(propertyValues)) {
            return;
        }
        //遍历propertyValues 分别填充name和value属性
        for (PropertyValue pv : propertyValues) {
            //对应着bean的属性名称
            String name = pv.getName();
            //对应着bean的属性值
            Object value = pv.getValue();
            //真正的值
            Object valueToUse = null;
            //value 我们需要确认他的类型
            if (value instanceof RuntimeBeanReference) {
                RuntimeBeanReference ref = (RuntimeBeanReference) value;
                valueToUse = getBean(ref.getRef());
            } else if (value instanceof TypeStringValue) {
                TypeStringValue tsv = (TypeStringValue) value;
                String val = tsv.getValue();
                Class<?> targetType = tsv.getTargetType();
                if (targetType == Integer.class) {
                    valueToUse = Integer.parseInt(val);
                } else if (targetType == String.class) {
                    valueToUse = val;
                } else if (targetType == Long.class) {
                    valueToUse = Long.parseLong(val);
                } else {
                    //其他的类型
                }
            }
            //设置属性值
            ReflectionUtils.setProperty(singleton, name, valueToUse);
        }
    }

    /**
     * 通过Class 通过构造生成实例
     *
     * @param cls
     * @return
     */
    protected Object createBeanInstance(Class<?> cls) {
        return ReflectionUtils.createObject(cls);
    }

    /**
     * 将className解析为Class
     *
     * @param className
     * @return
     */
    protected Class<?> resolveClassName(String className) {
        try {
            return Class.forName(className);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 通过Class创建bean
     *
     * @param type
     * @return
     */
    @Override
    public Object createBean(Class type) {
        return null;
    }
}
